package org.lc.stk.service.course.impl;

import java.util.ArrayList;
import java.util.List;

import org.lc.stk.dao.course.CourseRepository;
import org.lc.stk.model.course.Course;
import org.lc.stk.service.course.CourseService;
import org.lc.stk.service.exception.BusinessException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import jakarta.persistence.criteria.Predicate;

/**
 * 课程服务实现类
 */
@Service
@Transactional(readOnly = true)
public class CourseServiceImpl implements CourseService {

    private final CourseRepository courseRepository;

    public CourseServiceImpl(CourseRepository courseRepository) {
        this.courseRepository = courseRepository;
    }

    @Override
    @Transactional
    public Course save(Course course) {
        // 验证课程名称是否已存在
        if (existsByName(course.getName())) {
            throw new BusinessException("课程名称已存在: " + course.getName());
        }
        // 验证课程代码是否已存在
        if (courseRepository.existsByCode(course.getCode())) {
            throw new BusinessException("课程代码已存在: " + course.getCode());
        }

        // 设置默认状态为启用
        course.setState(Course.CourseState.ACTIVE);
        
        // 验证必填字段
        validateCourse(course);

        return courseRepository.save(course);
    }

    @Override
    @Transactional
    public Course update(Course course) {
        Course existingCourse = courseRepository.findById(course.getId())
                .orElseThrow(() -> new BusinessException("课程不存在: " + course.getId()));

        // 如果更改了课程名称，需要验证新名称是否已存在
        if (!existingCourse.getName().equals(course.getName()) && 
                existsByName(course.getName())) {
            throw new BusinessException("课程名称已存在: " + course.getName());
        }

        // 如果更改了课程代码，需要验证新代码是否已存在
        if (!existingCourse.getCode().equals(course.getCode()) &&
                courseRepository.existsByCode(course.getCode())) {
            throw new BusinessException("课程代码已存在: " + course.getCode());
        }

        // 验证必填字段
        validateCourse(course);

        // 更新字段
        existingCourse.setName(course.getName());
        existingCourse.setCode(course.getCode());
        existingCourse.setShortName(course.getShortName());
        existingCourse.setDepartment(course.getDepartment());
        existingCourse.setMajorCengcis(course.getMajorCengcis());
        existingCourse.setState(course.getState() == 1 ? Course.CourseState.ACTIVE : Course.CourseState.INACTIVE);

        return courseRepository.save(existingCourse);
    }

    @Override
    @Transactional
    public void delete(Integer id) {
        Course course = findById(id);
        course.setState(Course.CourseState.INACTIVE);
        courseRepository.save(course);
    }

    @Override
    public Course findById(Integer id) {
        return courseRepository.findById(id)
                .orElseThrow(() -> new BusinessException("课程不存在: " + id));
    }

    @Override
    public List<Course> findAll() {
        return courseRepository.findAll();
    }

    @Override
    public boolean existsByName(String name) {
        return courseRepository.existsByName(name);
    }

    @Override
    public boolean existsById(Integer id) {
        return courseRepository.existsById(id);
    }

    // 保留现有的其他查询方法
    public Page<Course> findCourses(String name, String code, Long departmentId,
                                Long majorId, Long cengciId, Pageable pageable) {
        Specification<Course> spec = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();

            if (StringUtils.hasText(name)) {
                predicates.add(cb.like(root.get("name"), "%" + name + "%"));
            }

            if (StringUtils.hasText(code)) {
                predicates.add(cb.equal(root.get("code"), code));
            }

            if (departmentId != null) {
                predicates.add(cb.equal(root.get("department").get("id"), departmentId));
            }

            // majorId和cengciId需要通过majorCengcis关联查询
            if (majorId != null || cengciId != null) {
                var majorCengciJoin = root.join("majorCengcis");
                if (majorId != null) {
                    predicates.add(cb.equal(majorCengciJoin.get("major").get("id"), majorId));
                }
                if (cengciId != null) {
                    predicates.add(cb.equal(majorCengciJoin.get("cengci").get("id"), cengciId));
                }
            }

            return cb.and(predicates.toArray(new Predicate[0]));
        };

        return courseRepository.findAll(spec, pageable);
    }

    public List<Course> findCoursesByDepartment(Long departmentId) {
        return courseRepository.findByDepartmentId(departmentId);
    }

    public List<Course> findCoursesByMajor(Long majorId) {
        Specification<Course> spec = (root, query, cb) -> {
            var majorCengciJoin = root.join("majorCengcis");
            return cb.equal(majorCengciJoin.get("major").get("id"), majorId);
        };
        return courseRepository.findAll(spec);
    }

    public List<Course> findCoursesByCengci(Long cengciId) {
        Specification<Course> spec = (root, query, cb) -> {
            var majorCengciJoin = root.join("majorCengcis");
            return cb.equal(majorCengciJoin.get("cengci").get("id"), cengciId);
        };
        return courseRepository.findAll(spec);
    }

    public boolean isCodeExists(String code) {
        return courseRepository.existsByCode(code);
    }

    private void validateCourse(Course course) {
        if (!StringUtils.hasText(course.getName())) {
            throw new BusinessException("课程名称不能为空");
        }

        if (!StringUtils.hasText(course.getCode())) {
            throw new BusinessException("课程代码不能为空");
        }

        if (course.getDepartment() == null || course.getDepartment().getId() == null) {
            throw new BusinessException("所属单位不能为空");
        }

        if (course.getMajorCengcis() == null || course.getMajorCengcis().isEmpty()) {
            throw new BusinessException("专业层次不能为空");
        }
    }
}
